from flask import Flask
from flask_socketio import SocketIO, emit
import threading
import json
import sqlite3
import sys
import os
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../../')))
import backend.P2P.auth as auth
import backend.P2P.node_find as node_find
import backend.P2P.private_chat as private_chat
import backend.P2P.group_chat as group_chat
import backend.P2P.info_sync as info_sync
import backend.P2P.add_friends as add_friends
import backend.P2P.device_management as device_managment
import backend.DID.Certification_Management as  Certification_Managementimport backend.P2P.device_management as device_managment
import backend.DID.Certification_Management as  Certification_Management
from private_chat import Private_chat

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, cors_allowed_origins='*')  # 允许跨域连接

PATH = "backend\image.png"
group_members = {}
private_chat= None

import base64

def path_to_base64(file_path,mime_type="image/png"):
    with open(file_path, "rb") as f:
        encoded = base64.b64encode(f.read()).decode('utf-8')
        return f"data:{mime_type};base64,{encoded}"


def convert_to_url(relative_path, base_url="http://192.168.72.122:5000/"):
    # 确保路径统一为正斜杠并去除开头的 "./"
    web_path = relative_path.replace("\\", "/").lstrip("./")
    return base_url.rstrip("/") + "/" + web_path

# 响应封装
def packageResponse(status: str, action: str, data):
    return {
        "status": status,
        "action": action,
        "data": data
    }

def loadHistoryResponse(status: str, action: str,type:str,id:str ,data):
        return {
        "status": status,
        "action": action,
        "type":type,
        "id":id,
        "data": data
    }

@socketio.on("server")
def handle_action(request):
    print(request)
    global private_chat
    try:
        action = request.get("action")
        info = request.get("data")

        if action == "regist":
            username = request.get("username")
            password = request.get("password")
            id= auth.regist(username, password)
            if id:
                data = {
                    "image_path": PATH,
                    "id":id
                }
                response = packageResponse("success", "register", data)
            else:
                print("失败")
                response = packageResponse("fail", "registResponse", {"reason": "密码超过六位 or 创建身份失败"})

        elif action == "login":
            username = request.get("username")
            password = request.get("password")
            id= request.get("did")
            result = auth.login(id,username, password)
            if result==1:
                data = {"image_path": convert_to_url(PATH),
                        "type":"host"
                        }
                response = packageResponse("success", "loginResponse", data)
            elif result==2:
                data = {"image_path": convert_to_url(PATH),
                        "type":"guest"
                        }
                response = packageResponse("success", "loginResponse", data)
            else:
                response = packageResponse("fail", "loginResponse", {"reason": "Invalid username or password"})

        elif action == "friendApply":
            id = info.get("id")
            name = info.get("name")
            result = add_friends.SendApply(id, name)
            print(f"结果为：{result}")
            if result:
                response = packageResponse("success", "friendApplyResponse", {"id":id})
            else:
                response = packageResponse("fail", "friendApplyResponse", {"reason": "Send error"})

        elif action == "friendAccept":
            id = info.get("id")
            name = info.get("name")
            result = add_friends.Agreement(id,name)
            if result:
                response = packageResponse("success", "friendacceptResponse", {"id":id})
            else:
                response = packageResponse("fail", "friendacceptResponse", {"reason": "Send error"})

        elif action == "scanFriend":
            threading.Thread(target=node_find.scan, daemon=True).start()
            threading.Thread(target=add_friends.retry_agreement).start()
            threading.Thread(target=add_friends.retry_requests).start()
            response = packageResponse("success", action, [])

        elif action == "loadApply":
            print("loadApply")
            friend_list = node_find.Get_friendlist()
            # print("friend_list 类型:", type(friend_list))
            print(friend_list)
            data = {
            fid: {
                "name": f_info["name"],
                "status": f_info.get("status", 0)
            } for fid, f_info in friend_list.items()
         }
            if data is not None:
                response = packageResponse("success", "loadApplyResponse", data)

            else:
                response = packageResponse("fail","loadApplyResponse", {"reason": "Send error"})       
        elif action=="loadAcceptList":
            friend_list=add_friends.load_accept()
            print(friend_list)
            if friend_list is not None:
                response = packageResponse("success", "loadAcceptListResponse", friend_list)
            else:
                response = packageResponse("fail","loadAcceptListResponse", {"reason": "Send error"})
        # elif action == "retryFriendrequest":
        #     add_friends.retry_agreement()
        #     add_friends.retry_requests()
        #     response = packageResponse("success", action, [])

        elif action == "privateListen":
            print("private_listen")
            global private_chat
            private_chat = Private_chat(socketio)
            # add_friends.bind(socketio)
            threading.Thread(target=add_friends.bind, args=(socketio,), daemon=True).start()
            print("私聊监听线程已启动")
            group_chat.recv_message(socketio)
            print("群聊监听线程已启动")
            response = packageResponse("success",  "privateListenResponse", [])

        elif action == "privateSend":
            print(f"request:{request}")
            id = request.get("receiverId")
            name=request.get("sender")
            message = request.get("message")
            timestamp= request.get("timestamp")
            print(f"id为{id}")
            # result = request.client(message, id,timestamp)
            private = Private_chat(socketio)
            result = private.client(message, id,timestamp,name)
            print(result)
            if result:
                response = packageResponse("success",  "privateSendResponse", [])
            else:
                response = packageResponse("fail", "privateSendResponse", {"reason": "Send error"})
        elif  action=="loadHistory":
            id = request.get("id")
            # print(f"加载历史记录，id为：{id}")
            type_ = request.get("type")
            result=None
            if type_=="friend":
                result = add_friends.load_history(id)

            elif type_=="group":
                print(f"加载群聊历史记录，id为：{id}")#打印为空
                result = group_chat.load_groupChat_history(id)
            else :
                print("没有type")    
            print(f"加载群聊历史记录结果：{result}")
            if result:
                response =  loadHistoryResponse("success","loadHistoryResponse", type_,id,id,result)
            else:
                response =  loadHistoryResponse("fail","loadHistoryResponse", type_,id, {"reason": "Send error"})
       
        elif action=="friendDelete":
            # pass
            id = info.get("id")
            name = info.get("name")
            result = add_friends.delete_friend(id, name)
            print(f"结果为：{result}")
            if result:
                response = packageResponse("success", "friendDeleteResponse", {"id":id})
            else:
                response = packageResponse("fail", "friendDeleteResponse", {"reason": "Send error"})
        elif action=="loadDevice":
            id = request.get("sender")
            result = device_managment.add_device(id)
            print(f"结果为：{result}")
            if result:
                response = packageResponse("success", "loadDeviceResponse", result)
            else:
                response = packageResponse("fail", "loadDeviceResponse", {"reason": "Send error"})
        # elif action=="loadDevice":
        #群聊聊天 
        elif action == "groupChat":
            
            sender_did = request.get("sender")
            groupId = request.get("groupId")
            message = request.get("data")
            groupname = message.get("groupname")
            result = group_chat.send_message(action,sender_did, groupname, groupId, message)
            print(f"群聊发送结果：{result}")
            if result:
                response = packageResponse("success","groupChatResponse",result)
            else:
                response = packageResponse("fail","groupChatResponse",{
                    "reason":"send error"
                })
        
        # #点击“创建群聊”时的接口
        # elif action == "createGroup":
        #     creator_did = request.get("sender")#群主DID号
        #     group_member = request.get("receiver")#群成员信息
        #     create_time = info.get("timestamp")
        #     result = group_chat.createGroup(creator_did,group_member,create_time)
        #     # result = {
        #     #     "groupId":"group_123",
        #     #     "groupName":"p2p!!!"
        #     # }
        #     if result:
        #         response = packageResponse("success","createGroupResponse",result)
        #     else:
        #         response = packageResponse("fail","createGroupResponse",{"result":"fail to create a group"})
                #点击“创建群聊”时的接口
        elif action == "createGroup":
            creator_did = request.get("sender")#群主DID号
            group_member = request.get("receiver")#群成员信息
            create_time = info.get("timestamp")
            groupname = info.get("groupName")
            result = group_chat.createGroup(groupname,creator_did,group_member,create_time)
            groupname = info.get("groupName")
            result = group_chat.createGroup(groupname,creator_did,group_member,create_time)
            # result = {
            #     "groupId":"group_123",
            #     "groupName":"p2p!!!"
            # }
            if result:
                response = packageResponse("success","createGroupResponse",result)
            else:
                response = packageResponse("fail","createGroupResponse",{"result":"fail to create a group"})
        
        #消息同步,基础信息或者聊天记录的同步
        elif action=="infoSync":
             my_did = info.get("my_did")
             modules = info.get("modules")
             result = info_sync.send_sync_request_to_host(my_did,modules)
             if result:
                 response = packageResponse("success","infoSyncResponse")
             else:
                 response = packageResponse("fail","infoSyncResponse",{"reason":"fail to info_sync"})
              
        #加载好友信息的接口,通讯录和创建群聊选择好友，以及所有需要加载好友列表的地方都可以使用
        elif action =="loadFriend":
            owner = request.get("sender")
            # with sqlite3.connect("p2p.db", check_same_thread=False) as conn:
            # cursor = conn.cursor()
            # cursor.execute('''''')
            result = info_sync.get_all_friends(owner) 
            icon =path_to_base64("backend\image.png")

            if result:
                response = packageResponse("success","loadFriendResponse",result)
            else:
                response = packageResponse("fail","loadFriendResponse",{"reason":"fail to load friend information"})

            #加载群聊信息的接口
        elif action == "loadGroup":
            creator = request.get("sender")
            result = info_sync.get_all_groups(creator)

            icon =path_to_base64("backend/P2P/小黑.png")
            result =[{
                "icon":icon,
                "id": "group_123456",               
                "name": "p2p" ,          			
                "online":True,
                "ip": "192.168.70.15",		
            }]
          
            if result:
                response = packageResponse("success","loadGroupResponse",result)

            else:
                response = packageResponse("fail","loadGroupResponse",{"reason":"fail to load group information"})       
        
        #@群成员
        elif action == "notice":
             sender_did = request.get("sender")
             group_id = request.get("group_id")
             groupname = request.get("groupname")
             content = info.get("message")
             result = group_chat.send_message_with_remind(sender_did, groupname, group_id, content)
             
             if result:
                response = packageResponse("success","noticeResponse")
            
             else:
                 response = packageResponse("fail","noticeResponse",{"reason":"fail to notice group members"})

        #群主修改群名称
        elif action == "changeGroupname":
             
             result = group_chat. master_change_groupname(info)
             if result :
                 response = packageResponse("success","changeGroupnameResponse")
             
             else:
                 response = ("fail","changeGroupnameResponse",{"reason":"fail to change the groupname"})

        #处理非action的操作
        else:
            response = packageResponse("fail", action, {"reason": "Unsupported action"})

    except Exception as e:
        print("错误:", e)
        response = packageResponse("fail", "error", {"reason": str(e)})

    emit("client", response)  # 给客户端响应
    print(response)


# 2. 使用UDP广播发送加密消息
# 启动 SocketIO 服务
if __name__ == '__main__':
    # with sqlite3.connect("p2p.db", check_same_thread=False) as conn:
    #         cursor = conn.cursor()
    #         cursor.execute('''select id,host from current_user''')
    #         row = cursor.fetchone()
    #         if row[1] == 1:
    #             #如果是本机，程序一启动就要启动本机监听跨机请求的线程
    #             threading.Thread(target=info_sync.host_udp_listener, daemon=True).start()
    #         else:
    #             #如果是程序一启动就要启动跨机监听本机回复的线程
    #             threading.Thread(target=info_sync.listen_for_host_response, daemon=True).start()

    socketio.run(app, host='0.0.0.0', port=5000, debug=True)



